package com.tqjc.execute.step;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tqjc.area.entity.SteelPlate;
import com.tqjc.area.entity.Stock;
import com.tqjc.area.service.SteelPlateService;
import com.tqjc.area.service.StockService;
import com.tqjc.common.consts.NormalConst;
import com.tqjc.execute.cache.TaskStatus;
import com.tqjc.execute.cache.entity.WorkStatus;
import com.tqjc.execute.cache.service.CraneSteelCacheService;
import com.tqjc.execute.consts.WorkConst;
import com.tqjc.execute.exception.TaskRunningException;
import com.tqjc.execute.exception.UpstreamSteelInfoException;
import com.tqjc.execute.task.entity.Task;
import com.tqjc.execute.task.entity.TaskApart;
import com.tqjc.execute.task.service.impl.TaskApartServiceImpl;
import com.tqjc.execute.task.service.impl.TaskServiceImpl;
import com.tqjc.execute.thread.aysn.AysnEleTaskLogThread;
import com.tqjc.execute.utils.DateUtils;
import com.tqjc.execute.utils.HttpPLCUtils;
import com.tqjc.execute.utils.PlcOperator;
import com.tqjc.execute.work.CraneWorkFactory;
import com.tqjc.execute.work.callback.TaskCallback;
import com.tqjc.system.core.threadpool.ThreadPoolManager;
import com.tqjc.system.core.util.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;


@Slf4j
@Component
@Scope("prototype")
public class PlaceSteelPlateStep extends TaskApart implements TaskCallback {


    @Resource
    SteelPlateService steelPlateService;

    @Resource
    StockService stockService;

    @Resource
    CraneSteelCacheService craneSteelCacheService;

    @Resource
    CraneWorkFactory craneWorkFactory;
    @Resource
    TaskStatus taskStatus;

    @Value("${server_host}")
    private String serverHost;

    @Autowired
    private RestTemplate restTemplate;

    public PlaceSteelPlateStep() {
        this.setType("place");
    }

    @Override
    public void onPreExecute() {
        try {
            setBeginTime(new Date());

            //设置工作状态
            WorkStatus status = taskStatus.getWorkStatusByCraneType(getCraneType());
            status.setNowStep(getType());
            status.setNowSteelNum(getTask().getSteelNo());
            status.setUnnormalStatus("");
            taskStatus.setWorkStatusByCraneType(getCraneType(), status);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(getCraneType()+getType()+"前置出现异常", e);
        }
    }

    @Override
    public void onPostExecute() {
        try {
            WorkConst.cacheTaskMap.remove(getCraneType()+"_task");  //放板成功了，缓存中的task没用了，释放
            setEndTime(new Date());

            getTask().setTaskStatus(2);
            SpringUtils.getBean(TaskServiceImpl.class).saveOrUpdate(getTask());
            SpringUtils.getBean(TaskApartServiceImpl.class).insert(this);
            //修改步骤状态
            WorkStatus status = taskStatus.getWorkStatusByCraneType(getCraneType());
            status.setNowStep("");
            status.setNowSteelNum("");
            taskStatus.setWorkStatusByCraneType(getCraneType(), status);
            //增加钢板库存
            List<SteelPlate> steels2Place=getTask().getSteels4Offline();
            if(steels2Place!=null&&steels2Place.size()>0){
                for(SteelPlate item:steels2Place){
                    //获取当前垛位所有的钢板，判断层数
                    QueryWrapper<SteelPlate> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("area", "stock_" + getTask().getStockId());
                    List<SteelPlate> steelPlates = steelPlateService.list(queryWrapper);
                    Integer tier=0;
                    if(steelPlates!=null){
                        tier = steelPlates.size() + 1;
                    }else {
                        tier =1;
                    }
                    item.setArea("stock_" + getTask().getStockId());
                    item.setTier(tier);
                    item.setInStock(1);
                    steelPlateService.insert(item);
                }
            }
            //清除bean
            destroy();
        } catch (Exception e) {
            log.error(getCraneType()+getType()+"后置出现异常", e);
            e.printStackTrace();
        }
    }


    @Override
    public void setTaskApartByTask(Task task) {
        this.setCallback(this);
        super.setTaskApartByTask(task);

    }


    @Override
    public void customAction() throws TaskRunningException, UpstreamSteelInfoException {
        try {
            String craneType = this.getTask().getCraneType();
            //从天车PLC获取钢板号作为放置人物的钢板号
//            String steelNum = plcOperator.readValueByLabelAndCraneType(WorkConst.STEEL_NUM, getCraneType());
            //String steelNum = getTask().getSteelNum();
            //this.setSteelId(steelNum);
            String steelNum ="";
            List<SteelPlate> steels2Place=getTask().getSteels4Offline();
            if(steels2Place!=null&&steels2Place.size()>0){
                for(int i=0;i<steels2Place.size();i++){
                    if(i==0){
                        steelNum=steels2Place.get(i).getSteelId();
                    }else{
                        steelNum+=","+steels2Place.get(i).getSteelId();
                    }
                }
            }else{
                steelNum = getTask().getSteelNo();
            }
            this.setSteelNo(steelNum);
            //异步启动自动任务监控线程
            AysnEleTaskLogThread aysnEleTaskLogThread = AysnEleTaskLogThread.builder().flag(true).craneName(craneType).host(serverHost).restTemplate(restTemplate).build();
            ThreadPoolManager.getInstance().execute(aysnEleTaskLogThread);
            //清任务id
            HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.2",HttpPLCUtils.dataTypeList.get("int16"),"0","任务ID",false);
            //清任务启动信号
            HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.8.2",HttpPLCUtils.dataTypeList.get("bool"),"FALSE","任务启动",false);
            //清任务完成信号
            HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.120.5",HttpPLCUtils.dataTypeList.get("bool"),"FALSE","放板任务完成",false);

            //写入任务ID
            HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.2",HttpPLCUtils.dataTypeList.get("int16"),"2","任务ID",false);
            String stockNo=craneWorkFactory.getCraneWorkImpl(craneType).getData().getStockNo();
            //写入垛位
            if("11C北".equals(craneType)){
                if("1".equals(stockNo)){
                    HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.8.7",HttpPLCUtils.dataTypeList.get("bool"),"TRUE","垛位1",false);
                    HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.9",HttpPLCUtils.dataTypeList.get("bool"),"FALSE","垛位2",false);
                }else {
                    HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.9",HttpPLCUtils.dataTypeList.get("bool"),"TRUE","垛位2",false);
                    HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.8.7",HttpPLCUtils.dataTypeList.get("bool"),"FALSE","垛位1",false);
                }
            }else if("11C南".equals(craneType)){
                if("1".equals(stockNo)){
                    HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.8.7",HttpPLCUtils.dataTypeList.get("bool"),"TRUE","垛位1",false);
                    HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.9",HttpPLCUtils.dataTypeList.get("bool"),"FALSE","垛位2",false);

                }else {
                    HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.9",HttpPLCUtils.dataTypeList.get("bool"),"TRUE","垛位2",false);
                    HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.8.7",HttpPLCUtils.dataTypeList.get("bool"),"FALSE","垛位1",false);
                }
            }
            else {
                HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.8.7",HttpPLCUtils.dataTypeList.get("bool"),"TRUE","垛位1",false);
            }
            //写入任务启动
            HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.8.2",HttpPLCUtils.dataTypeList.get("bool"),"TRUE","任务启动",false);
            log.info("{}天车自动放板步骤任务启动",getTask().getCraneType());
            boolean isFinished = false;
            String isFinishStr="";
            Date startDate=new Date();
            while (!isFinished) {
                boolean overTime= DateUtils.isOverTimeByNow(startDate,100000);//超过100秒未完成，退出等待。
                if(overTime){
                    //log.info("等待{}天车自动放板步骤任务完成超时",getTask().getCraneType());
                    WorkStatus status = taskStatus.getWorkStatusByCraneType(getCraneType());
                    status.setUnnormalStatus("等待放板任务完成超时");
                    taskStatus.setWorkStatusByCraneType(getCraneType(), status);

                    boolean isStartLogo= craneWorkFactory.getCraneWorkImpl(getCraneType()).getData().getStartLogo();
                    if(!isStartLogo){
                        break;
                    }
                    //return;
                }
                isFinishStr= HttpPLCUtils.plcReadbc(restTemplate,serverHost,craneType,"放板任务完成",false);
                if ("true".equalsIgnoreCase(isFinishStr)) {
                    //清任务id
                    HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.2",HttpPLCUtils.dataTypeList.get("int16"),"0","任务ID",false);
                    //清任务启动信号
                    HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.8.2",HttpPLCUtils.dataTypeList.get("bool"),"FALSE","任务启动",false);
                    //清任务完成信号
                    HttpPLCUtils.plcWritebcPlus(restTemplate,serverHost,craneType,"DB20.120.5",HttpPLCUtils.dataTypeList.get("bool"),"FALSE","放板任务完成",false);

                    isFinished = true;
                    log.info("PLC反馈{}天车自动放板步骤任务完成",getTask().getCraneType());
                }
                String taskFlag = HttpPLCUtils.plcReadbc(restTemplate, serverHost, craneType, "任务中止", false);
                if("true".equalsIgnoreCase(taskFlag)){
                    log.info("天车执行自动放板步骤时，监听到任务中止信号");
                    aysnEleTaskLogThread.setFlag(false);
                    throw new TaskRunningException("任务人工停止",craneType);
                }
            }
            aysnEleTaskLogThread.setFlag(false);
            WorkStatus status = taskStatus.getWorkStatusByCraneType(getCraneType());
            status.setUnnormalStatus("");
            taskStatus.setWorkStatusByCraneType(getCraneType(), status);
        } catch (UpstreamSteelInfoException ee){
            WorkStatus status = taskStatus.getWorkStatusByCraneType(getCraneType());
            status.setUnnormalStatus(ee.getMessage());
            taskStatus.setWorkStatusByCraneType(getCraneType(), status);
            throw ee;
        }catch (Exception e) {
            WorkStatus status = taskStatus.getWorkStatusByCraneType(getCraneType());
            status.setUnnormalStatus(e.getMessage());
            taskStatus.setWorkStatusByCraneType(getCraneType(), status);
            e.printStackTrace();
            throw new TaskRunningException(e.getMessage(), getTask().getCraneType());
        }
    }


    @Override
    public void destroy() throws Exception {

    }

    @Override
    public void afterPropertiesSet() throws Exception {

    }
}
